#include "sendmsg.h"
#include "channel.h"

// son channel id ====== 0
// parent channel id === 1

#define SHM_SZ 1024

int s[2];    /* Pair of sockets */
int channel_id;
bool to_quit = false;
bool sig_child = false;
http_process_t   http_processes[HTTP_MAX_PROCESSES];
int              http_last_process;

void *psm;
int shmid;

int setnonblocking( int fd )
{
    int opts;
 
    if( fd<=0 )
        return -1;
 
    opts = fcntl( fd, F_GETFL );
    if( opts<0 )
        return -1;
 
    if( fcntl( fd, F_SETFL, opts|O_NONBLOCK ) < 0 )
        return -1;
 
    return 0;
}

int create()
{
    int z, s;        /* Status return code */
    pid_t pid;
    
    for (s = 0; s < http_last_process; s++) {
        if (http_processes[s].pid == -1) {
            break;
        }
    }
    
    z = socketpair(AF_LOCAL,SOCK_STREAM,0,http_processes[s].channel);
    channel_id = http_processes[s].channel[1];
    
    pid = fork();
    
    switch (pid) {
        case -1: return -1;
        case 0: work_process_cycle();break;
        default: break;
    }
    
    http_processes[s].pid = pid;   
    http_processes[s].exited = 0;

    http_processes[s].data = NULL;
    http_processes[s].name = NULL;
    http_processes[s].exiting = 0;
    
    if (s == http_last_process) {
        http_last_process++;
    }
    
    return 0;
}

void SignalHandler(int signo)
{
    switch (signo) {
        case SIGTERM:
            to_quit = true;
            break;
        case SIGCHLD:
            sig_child = true;
            break;
        default:
            break;    
    }
}

int initmain(int argc, char **argv)
{

    http_channel_t  ch;        
    int pid;
   
    
    if (argc == 3) {    
        if (strcmp(argv[1], "stop") == 0 ) {
            pid = atoi(argv[2]);
            kill(pid, SIGTERM);
            exit(0);
        }
    }
    
    return 0;
}

/*
 * Read from socket s[0]:
 * son process want to exit;
 */
int work_process_cycle()
{
    http_channel_t ch;
    int i;
        
    for ( ; ; ) {                
        //llog("child process %d now running\n", getpid());        
        if (to_quit) {
            llog("child process %d prep exit\n", getpid());
            
            exit(0);
        }        
        
        sleep(1);
    }
    
    return 0;
}

void child_change_live(int chdid)
{
    for (int i = 0; i < http_last_process; i++) {
        if (http_processes[i].pid == chdid) {
            llog("i = %d \n", i);
            llog("chdid = %d \n", chdid);
            http_processes[i].exited = 1;
            break;
        }
    }
}

int child_real_live()
{
    int child_live = 0;
    for (int i = 0; i < http_last_process; i++) {
        if (!http_processes[i].exited) {
            child_live++;
        }        
    }
    
    return child_live;
}

int main(int argc,char **argv)
{   
    int live = 1;
    int status;      
    
    signal(SIGTERM, SignalHandler);    
    signal(SIGCHLD, SignalHandler);
    

    initmain(argc, argv);   
    
    for (int i=0; i<2; i++) {
        create();                  
    }
        
    for ( ; ; ) {            
    
        live = child_real_live();
        
        if (!live) {
            llog("main process exit\n");
            exit(0);
        }
    
        if (to_quit) {                    
            http_channel_t ch;            
            ch.command = HTTP_CMD_QUIT;
            
            for (int i = 0; i < http_last_process; i++) {
                kill(http_processes[i].pid, SIGTERM);    
            }                       
        }
        
        if (sig_child) {
            int chdid = wait( &status );  
            llog("child process %d exit succeed!\n", chdid);
            child_change_live(chdid);                  
            
            sig_child = 0;
        }
        
        sleep(1);
    }        
    
    
    return 0;
}
//g++ -g -o sendmsg sendmsg.cpp channel.cpp
